package com.ea.eadp.nexus.test.pageDefinition.mobile;

import com.ea.eadp.test.shared.TestException;
import com.ea.eadp.test.shared.utility.LogHelper;
import com.ea.eadp.test.shared.utility.UtilHelper;
import com.ea.nova.test.client.SystemPropertiesHelper;
import com.google.common.base.Predicate;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;

import com.ea.eadp.nexus.test.common.TestUtil;
import com.ea.eadp.nexus.test.pageDefinition.TwoFactorAuthClient;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public abstract class TFAClient_WebBasedMobile implements TwoFactorAuthClient<WebDriver> {
    // common elements
    public static final By SUBMIT1 = By.cssSelector("#loginForm input[type='submit']");
    public static final By SUBMIT2 = By.id("btnLogin");
    public static final By TFASUBMIT = By.id("btnTFALogin");
    public static final By ERROR_MESSAGE = By.cssSelector("#loginForm .orange-box-error");
    public static final By ERROR_MESSAGE_EMPTY_CODE = By.xpath(".//*[@id='origin-tfa-container']/div/span[3]");
    public static final By ERROR_MESSAGE_LOGIN = By.cssSelector("#loginForm .general-error");
    // regular-auth elements
    public static final By USERNAME = By.id("email");
    public static final By PASSWORD = By.id("password");

    private WebDriver client = null;

    @Override
    public WebDriver getClient() {
        return client;
    }

    @Override
    public void setClient(WebDriver client) {
        this.client = client;
    }

    @Override
    public Status getStatus() throws Exception {
        try {
            client.findElement(USERNAME);
            client.findElement(PASSWORD);
            return Status.REGULAR_AUTH;
        } catch (NoSuchElementException e) {
            // do nothing
        }

        return Status.UNKNOWN;
    }

    public void goAuthentication(String mobileDeviceId) throws Exception {
        String url = TestUtil.BaseConnectURI() + TestUtil.SigninMobileConnectURI();
        if(mobileDeviceId != null) {
            url += String.format("&machineProfileKey=%s", mobileDeviceId);
        }
        getClient().get(url);
    }

    @Override
    public void goAuthentication() throws Exception {
        client.get(TestUtil.BaseConnectURI() + TestUtil.SigninWebConnectURI());
    }

    @Override
    public void goAuthenticationForSpecific(String clientId) throws Exception {
        client.get(TestUtil.BaseConnectURI() + TestUtil.getGenericConnectUri(clientId, "web/login"));
    }

    @Override
    public void goAuthenticationForSpecific(String clientId, String redirectUri) throws Exception {
        client.get(TestUtil.BaseConnectURI() + TestUtil.getGenericConnectUri(clientId, "web/login", redirectUri));
    }

    @Override
    public void login(String username, String password) throws Exception {
        client.findElement(USERNAME).clear();
        client.findElement(USERNAME).sendKeys(username);
        client.findElement(PASSWORD).clear();
        client.findElement(PASSWORD).sendKeys(password);
        try {
            client.findElement(SUBMIT1).click();
        }catch(NoSuchElementException e) {
            client.findElement(SUBMIT2).click();
        }
    }

    @Override
    public String getErrorMessage() throws Exception {
        String result = null;
        try {
            result = client.findElement(ERROR_MESSAGE_LOGIN).getText();
        } catch (NoSuchElementException e) {
            // do nothing
        } finally {
            if (null != result && !result.isEmpty())
                return result;
        }
        try {
            result = client.findElement(ERROR_MESSAGE).getText();
        } catch (NoSuchElementException e) {
            // do nothing
        } finally {
            if (null != result && !result.isEmpty())
                return result;
        }

        try {
            result = client.findElement(ERROR_MESSAGE_EMPTY_CODE).getText();
        } catch (NoSuchElementException e) {
            // do nothing
        } finally {
            if (null != result && !result.isEmpty())
                return result;
        }

        return null;
    }
    public String getErrorMessage(By by) throws Exception {
        String result = null;

        try {
            result = client.findElement(by).getText();
        } catch (NoSuchElementException e) {
            // do nothing
        } finally {
            if (null != result && !result.isEmpty())
                return result;
        }

        return null;
    }
    @Override
    public String getInfoMessage() throws Exception {

        return null; // TODO no info message DOM found...
    }

    @Override
    public void close() throws Exception {
        if (null != client)
            client.quit();
    }


    public void navigate(String url) {
        LogHelper.instance.logMessage("Navigate to %s", url);
        client.navigate().to(url);
    }

    public WebElement getWebElement(By by) {
        try {
            return client.findElement(by);
        } catch (NoSuchElementException ex) {
            LogHelper.instance.logWarn("Element not found. " + by.toString());
            return null;
        }
    }

    public boolean IsWebElementPresent(By by) {
        return getWebElement(by) != null;
    }

    public By GetAnyPresentWebElement(By... bys) {
        for (By by : bys) {
            if (getWebElement(by) != null) {
                return by;
            }
        }
        return null;
    }

    public void refreshPage() {
        String url = client.getCurrentUrl();
        navigate(url);
    }

    public void waitForWebElementPresent(By by) {
        WebDriverWait wait = new WebDriverWait(client, 30, 1000);
        wait.until(ExpectedConditions.visibilityOfElementLocated(by));
    }

    public By waitForAnyWebElementPresent(By... bys) {
        for (int i = 0; i < 30; i++) {
            By by = GetAnyPresentWebElement(bys);
            if (by != null) {
                return by;
            } else {
                UtilHelper.sleep(1000);
            }
        }

        throw new TestException("none of expected element shows");
    }
}
